package com.xl.Test;

import com.xl.annotation.PrefixName;
import com.xl.entity.Person;
import com.xl.entity.User;
import com.xl.entity.UserBak;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 1 演示 如何通过反射拿到注解对象，以及注解对象的属性值，
 * 2 演示 如何通过反射拿到一个类上的注解，字段上的注解，
 * 3 演示 如果通过反射执行一个类的私有方法
 * 拿到类和属性上面的注解  相关类的继承关系 Person->User->UserBak
 */
public class TestAnnoReflect {
    public static void main(String[] args) {
        //拿到Person类上的PrefixName注解
        PrefixName personPrefix = Person.class.getAnnotation(PrefixName.class);
        System.out.println(personPrefix);  //null因为我确实是没有给Person加注解
        PrefixName userPrefix = User.class.getAnnotation(PrefixName.class);
        System.out.println(userPrefix);    //不是null，我再该类上加了注解
        PrefixName userBak = UserBak.class.getAnnotation(PrefixName.class);
        System.out.println(userBak);       //不是null，虽然我没有在该类上加注解，但是他继承值user，且注解类中使用到了Inherent注解

        System.out.println("--------------");

        PrefixName annotation = User.class.getAnnotation(PrefixName.class);
        //拿到类上的注解的value值
        System.out.println(annotation.value());
        //通过反射拿到这个类中的字段
        Field[] fields = User.class.getFields();
        System.out.println("fields");
        //todo 不知道为啥这里没有打印出来任何东西
        for (Field field : fields) {
            PrefixName anno1 = field.getAnnotation(PrefixName.class);
            System.out.println("注解value值：" + anno1.value());
            System.out.println("字段名：" + field.getName() + "数据类型：" + field.getType());
        }

        Field[] declaredFields = User.class.getDeclaredFields();
        System.out.println("declaredFields仅仅是拿到当前类中的输出");
        for (Field declaredField : declaredFields) {
            PrefixName anno1 = declaredField.getAnnotation(PrefixName.class);
            System.out.println("注解value值：" + anno1.value());
            System.out.println("字段名：" + declaredField.getName() + "数据类型：" + declaredField.getType());
        }

        //拿到user类里面的方法
        System.out.println("通过反射拿到类里面的方法");
        Method[] declaredMethods = User.class.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod.getName());
        }

        System.out.println("通过方法名和参数类型拿到指定的方法");
        try {
            Method eat = User.class.getDeclaredMethod("eat", String.class);
            eat.setAccessible(true); //因为eat方法是私有的，现在让他变为可以访问
            System.out.println(eat.getName());
            //第一个参数是User对象的实例
            eat.invoke(new User(), "hello");
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }
}
